﻿using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Linq;
using Silent.API.Ukrbash.EventArgs;
using Silent.API.Ukrbash.Model;

namespace Silent.API.Ukrbash
{
    public class UkrbashApi
    {
        private readonly string apiKey;
        private readonly BashQueryBuilder builder;

        #region Events

        public event EventHandler<QuotesDataEventArgs> PublishedQuotesCompleted;
        protected virtual void OnPublishedQuotesCompleted(QuotesDataEventArgs e)
        {
            EventHandler<QuotesDataEventArgs> handler = PublishedQuotesCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<QuotesDataEventArgs> UpcomingQuotesCompleted;
        protected virtual void OnUpcomingQuotesCompleted(QuotesDataEventArgs e)
        {
            EventHandler<QuotesDataEventArgs> handler = UpcomingQuotesCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<QuotesDataEventArgs> RandomQuotesCompleted;
        protected virtual void OnRandomQuotesCompleted(QuotesDataEventArgs e)
        {
            EventHandler<QuotesDataEventArgs> handler = RandomQuotesCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<QuotesDataEventArgs> TheBestQuotesCompleted;
        protected virtual void OnTheBestQuotesCompleted(QuotesDataEventArgs e)
        {
            EventHandler<QuotesDataEventArgs> handler = TheBestQuotesCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<PicturesDataEventArgs> PublishedPicturesCompleted;
        protected virtual void OnPublishedPicturesCompleted(PicturesDataEventArgs e)
        {
            EventHandler<PicturesDataEventArgs> handler = PublishedPicturesCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<PicturesDataEventArgs> UpcomingPicturesCompleted;
        protected virtual void OnUpcomingPicturesCompleted(PicturesDataEventArgs e)
        {
            EventHandler<PicturesDataEventArgs> handler = UpcomingPicturesCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<PicturesDataEventArgs> RandomPicturesCompleted;
        protected virtual void OnRandomPicturesCompleted(PicturesDataEventArgs e)
        {
            EventHandler<PicturesDataEventArgs> handler = RandomPicturesCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<PicturesDataEventArgs> TheBestPicturesCompleted;
        protected virtual void OnTheBestPicturesCompleted(PicturesDataEventArgs e)
        {
            EventHandler<PicturesDataEventArgs> handler = TheBestPicturesCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<TagsDataEventArgs> TagsCompleted;
        protected virtual void OnTagsCompleted(TagsDataEventArgs e)
        {
            EventHandler<TagsDataEventArgs> handler = TagsCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<UsersDataEventArgs> UserListCompleted;
        protected virtual void OnUserListCompleted(UsersDataEventArgs e)
        {
            EventHandler<UsersDataEventArgs> handler = UserListCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<DataEventArgs<BashSiteInfo>> SiteInfoCompleted;
        protected virtual void OnSiteInfoCompleted(DataEventArgs<BashSiteInfo> e)
        {
            EventHandler<DataEventArgs<BashSiteInfo>> handler = SiteInfoCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<DataEventArgs<BashQuote>> QuoteByIdCompleted;
        protected virtual void OnQuoteByIdCompleted(DataEventArgs<BashQuote> e)
        {
            EventHandler<DataEventArgs<BashQuote>> handler = QuoteByIdCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<DataEventArgs<BashPicture>> PictureByIdCompleted;
        protected virtual void OnPictureByIdCompleted(DataEventArgs<BashPicture> e)
        {
            EventHandler<DataEventArgs<BashPicture>> handler = PictureByIdCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<DataEventArgs<BashUser>> UserByIdCompleted;
        protected virtual void OnUserByIdCompleted(DataEventArgs<BashUser> e)
        {
            EventHandler<DataEventArgs<BashUser>> handler = UserByIdCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }
        public event EventHandler<ObjectsDataEventArgs> SearchCompleted;
        protected virtual void OnSearchCompleted(ObjectsDataEventArgs e)
        {
            EventHandler<ObjectsDataEventArgs> handler = SearchCompleted;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion

        public UkrbashApi(string _apiKey)
        {
            apiKey = _apiKey;
            builder = new BashQueryBuilder(apiKey);
        }

        public List<BashQuote> GetPublishedQuotes()
        {
            var elements = XElement.Load(builder.BuildPublishedQuotesQuery()).Descendants("quote");
            var objects = elements.Select(Converter.XElementToQuote).ToList();
            OnPublishedQuotesCompleted(new QuotesDataEventArgs(objects));
            return objects;
        }
        public List<BashQuote> GetUpcomingQuotes()
        {
            var elements = XElement.Load(builder.BuildUpcomingQuotesQuery()).Descendants("quote");
            var objects = elements.Select(Converter.XElementToQuote).ToList();
            OnUpcomingQuotesCompleted(new QuotesDataEventArgs(objects));
            return objects;
        }
        public List<BashQuote> GetRandomQuotes()
        {
            var elements = XElement.Load(builder.BuildRandomQuotesQuery()).Descendants("quote");
            var objects = elements.Select(Converter.XElementToQuote).ToList();
            OnRandomQuotesCompleted(new QuotesDataEventArgs(objects));
            return objects;
        }
        public List<BashQuote> GetTheBestQuotes()
        {
            var elements = XElement.Load(builder.BuildTheBestQuotesQuery()).Descendants("quote");
            var objects = elements.Select(Converter.XElementToQuote).ToList();
            OnTheBestQuotesCompleted(new QuotesDataEventArgs(objects));
            return objects;
        }
        public List<BashPicture> GetPublishedPictures()
        {
            var elements = XElement.Load(builder.BuildPublishedPicturesQuery()).Descendants("picture");
            var objects = elements.Select(Converter.XElementToPicture).ToList();
            OnPublishedPicturesCompleted(new PicturesDataEventArgs(objects));
            return objects;
        }
        public List<BashPicture> GetUpcomingPictures()
        {
            var elements = XElement.Load(builder.BuildUpcomingPicturesQuery()).Descendants("picture");
            var objects = elements.Select(Converter.XElementToPicture).ToList();
            OnUpcomingPicturesCompleted(new PicturesDataEventArgs(objects));
            return objects;
        }
        public List<BashPicture> GetRandomPictures()
        {
            var elements = XElement.Load(builder.BuildRandomPicturesQuery()).Descendants("picture");
            var objects = elements.Select(Converter.XElementToPicture).ToList();
            OnRandomPicturesCompleted(new PicturesDataEventArgs(objects));
            return objects;
        }
        public List<BashPicture> GetTheBestPictures()
        {
            var elements = XElement.Load(builder.BuildTheBestPicturesQuery()).Descendants("picture");
            var objects = elements.Select(Converter.XElementToPicture).ToList();
            OnTheBestPicturesCompleted(new PicturesDataEventArgs(objects));
            return objects;
        }
        public List<BashTag> GetTags()
        {
            var elements = XElement.Load(builder.BuildTagsQuery()).Descendants("tag");
            var objects = elements.Select(Converter.XElementToTag).ToList();
            OnTagsCompleted(new TagsDataEventArgs(objects));
            return objects;
        }
        public List<BashUser> GetUserList()
        {
            var elements = XElement.Load(builder.BuildUserListQuery()).Descendants("user");
            var objects = elements.Select(Converter.XElementToUser).ToList();
            OnUserListCompleted(new UsersDataEventArgs(objects));
            return objects;
        }
        public List<object> GetSearch(string expression)
        {
            var elements = XElement.Load(builder.BuildSearchQuery(expression));
            var objects = new List<object>();
            var quotes = elements.Descendants("item").Where(x =>
                {
                    var typeElement = x.Element("type");
                    return typeElement != null && typeElement.Value == "quote";
                });
            objects.AddRange(quotes.Select(Converter.XElementToQuote));
            var pictures = elements.Descendants("item").Where(x =>
                {
                    var typeElement = x.Element("type");
                    return typeElement != null && typeElement.Value == "picture";
                });
            objects.AddRange(pictures.Select(Converter.XElementToPicture));
            OnSearchCompleted(new ObjectsDataEventArgs(objects));
            return objects;
        }
        public BashSiteInfo GetSiteInfo()
        {
            var element = XElement.Load(builder.BuildSiteInfoQuery());
            var objects = Converter.XElementToSiteInfo(element);
            OnSiteInfoCompleted(new DataEventArgs<BashSiteInfo>(objects));
            return objects;
        }
        public BashQuote GetQuoteById(int id)
        {
            var element = XElement.Load(builder.BuildQuoteByIdQuery(id)).Descendants("quote").FirstOrDefault();
            var objects = Converter.XElementToQuote(element);
            OnQuoteByIdCompleted(new DataEventArgs<BashQuote>(objects));
            return objects;
        }
        public BashPicture GetPictureById(int id)
        {
            var element = XElement.Load(builder.BuildPictureByIdQuery(id)).Descendants("picture").FirstOrDefault();
            var objects = Converter.XElementToPicture(element);
            OnPictureByIdCompleted(new DataEventArgs<BashPicture>(objects));
            return objects;
        }
        public BashUser GetUserById(int id)
        {
            var element = XElement.Load(builder.BuildUserByIdQuery(id)).Descendants("user").FirstOrDefault();
            var objects = Converter.XElementToUser(element);
            OnUserByIdCompleted(new DataEventArgs<BashUser>(objects));
            return objects;
        }
    }
}
